package com.fzj.example.socket.tcp.nonblock.nio;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Set;

/**
 * ClassName: NioSelServer
 * date: 2019/11/21 11:13
 * Description: TODO
 *
 * @author fanzj@bonree.com
 * @since JDK 1.8
 */
public class NioSelServer {
    public static void main(String[] args) {
        try {
            ServerSocketChannel ssc=ServerSocketChannel.open();
            ssc.bind(new InetSocketAddress(InetAddress.getByName("192.168.0.23"),8080));
            ssc.configureBlocking(false);
            Selector sel=Selector.open();
            ssc.register(sel, SelectionKey.OP_ACCEPT);
            ByteBuffer readBuff=ByteBuffer.allocate(1024);
            ByteBuffer writeBuff=ByteBuffer.allocate(1024);
            //编码
            writeBuff.put("服务端给你发送数据".getBytes());
            //复位
            writeBuff.flip();
            while(true){
                sel.select();
                Set< SelectionKey > set = sel.selectedKeys();
                set.stream().forEach(selectionKey -> {
                    set.remove(selectionKey);
                    //accept
                    if(selectionKey.isAcceptable()){
                        try {
                            SocketChannel socketChannel=ssc.accept();
                            socketChannel.configureBlocking(false);
                            socketChannel.register(sel,SelectionKey.OP_READ);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    if(selectionKey.isReadable()){
                        try {
                            SocketChannel socketChannel= (SocketChannel) selectionKey.channel();
                            //readBuff可写状态
                            readBuff.clear();
                            //写到readBuff
                            int len=socketChannel.read(readBuff);
                            if(len>0){
                                //readBuff可读状态，复位，数据不变
                                readBuff.flip();
                                //输出打印
                                System.out.println(Thread.currentThread().getName()+" server received: "+new String(readBuff.array(),0,len));
                                //切换到写感兴趣事件
                                selectionKey.interestOps(SelectionKey.OP_WRITE);
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    if(selectionKey.isWritable()){
                        try {
                            SocketChannel socketChannel= (SocketChannel) selectionKey.channel();
                            //rewind，读取位置更改,数据不变
                            writeBuff.rewind();
                            //writeBuff输出
                            socketChannel.write(writeBuff);
                            //writeBuff，复位
                            writeBuff.flip();
                            //切换到读感兴趣时间
                            selectionKey.interestOps(SelectionKey.OP_READ);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                });
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
